package com.yinhd.study.dockingPlatform.register;

import com.yinhd.study.dockingPlatform.utils.Md5Utils;
import org.apache.tomcat.util.http.parser.Authorization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: study
 * @description:
 * @Author: chengl
 * @create: 2022-05-05 17:11
 **/
public class Register {
    @Value("")
    String sendJson = "{\"RegisterObject\":{\"DeviceID\":\"41000000005030312222\"}}";

    String ip ="10.10.16.235";
    String registerUrl = "/VIID/System/Register";

    @Autowired
    Md5Utils MD5;

    public String register() throws IOException {
        boolean successs = false;//判断第一次响应是否成功
        Map<String,String> map_FirstReturn = null;
        try {
            //statusCode realm qop nonce
            map_FirstReturn = firstRequest(ip+registerUrl, "POST", sendJson);
            String statusCode = map_FirstReturn.get("statusCode");
            if(statusCode!=null && "401".equals(statusCode)){
                successs = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        boolean successs2 = false;
        if(successs){
            //第一次注册成功 获取响应头中的验证信息
            //				log.error("第一次请求注册成功");
            String Authorization = getResponseCkInfo(map_FirstReturn,countList);
            System.out.println("Authorization="+Authorization);
            //				log.error("Authorization:"+Authorization);
            //				String responseStr2 = RestClient.postByRest("/VIID/System/Register", sendJson, Authorization);
            String responseStr2 = restConnectForSecond(ip+"/VIID/System/Register", "POST", sendJson, Authorization);
            //				log.error("second R:"+responseStr2);
            //向发起方发送成功响应200 OK
            if("201".equals(responseStr2)){
                successs2 = true;
            }
            System.out.println("Authorization="+Authorization);
            System.out.println("response=="+responseStr2);
            return Authorization;
        }
        return  null;
    }

    public Map<String,String> firstRequest(String url,String method, String param) throws IOException {
        Map<String,String> returnMap = new HashMap<String, String>();
        URL restUrl=new URL(url);
        HttpURLConnection conn = (HttpURLConnection) restUrl.openConnection();
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setRequestMethod(method);
        conn.setUseCaches(false);
        conn.setRequestProperty("Accept-Charset", "UTF-8");//设置请求头
        //设置访问提交模式，表单提交
        conn.setRequestProperty("Content-Type","application/VIID+JSON");
        conn.setConnectTimeout(10000);//连接超时 单位毫秒
        conn.setReadTimeout(5000);//读取超时 单位毫秒

        //传递参数
        if (param != null) {
            byte[] bypes = param.toString().getBytes("utf-8");
            conn.getOutputStream().write(bypes);
        }
        //连接
        conn.connect();
        //传递参数
        Map<String, List<String>> map = conn.getHeaderFields();
        System.out.println("响应码："+conn.getResponseCode());
        returnMap.put("statusCode", conn.getResponseCode()+"");

        for (String key : map.keySet()) {
            System.out.println("响应key："+key);
            if(map.get(key)!=null){
                System.out.println("响应value："+map.get(key).get(0));
                if("WWW-Authenticate".equals(key)){
                    String responStr = map.get(key).get(0).replaceAll("Digest", "").replaceAll(" ", "");
                    if(responStr.indexOf("\r\n")!=-1){
                        System.out.println("有换行");
                    }else{
                        System.out.println("无换行");
                    }
                    String[] arr = responStr.split(",");
                    for (int i = 0; i < arr.length; i++) {
                        if(arr[i].indexOf("realm=")!=-1){
                            String realm = arr[i].replaceAll("realm=", "").replaceAll("\"", "");
                            returnMap.put("realm", realm);
                            System.out.println("realm:"+realm);
                        }else if(arr[i].indexOf("qop=")!=-1){
                            String qop = arr[i].replaceAll("qop=", "").replaceAll("\"", "");
                            returnMap.put("qop", qop);
                            System.out.println("qop:"+qop);
                        }else if(arr[i].indexOf("nonce=")!=-1){
                            String nonce = arr[i].replaceAll("nonce=", "").replaceAll("\"", "");
                            returnMap.put("nonce", nonce);
                            System.out.println("nonce:"+nonce);
                        }
                    }
                }
            }else{
                System.out.println("响应value：null");
            }
        }
        return returnMap;
    }

    public static String restConnectForSecond(String url,String method,String param,String authentication) throws IOException {
        URL restUrl=new URL(url);
        HttpURLConnection conn = (HttpURLConnection) restUrl.openConnection();
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setRequestMethod(method);
        conn.setUseCaches(false);
        //		conn.setRequestProperty("Accept-Charset", "UTF-8");
        //			conn.setRequestProperty("contentType", "UTF-8");
        //设置访问提交模式，表单提交
        //		conn.setRequestProperty("accept","application/json1");
        conn.setRequestProperty("Content-Type","application/json");
        conn.setRequestProperty("Authorization",authentication);
        conn.setConnectTimeout(10000);//连接超时 单位毫秒
        conn.setReadTimeout(5000);//读取超时 单位毫秒
        conn.connect();
        //传递参数
        if (param != null && !"".equals(param)) {
            byte[] bypes = param.toString().getBytes("utf-8");
            conn.getOutputStream().write(bypes);
        }
        InputStream inStream=conn.getInputStream();
        byte[] buffer = new byte[10240];
        int length = 0;
        String strResult = "";
        while ((length = inStream.read(buffer)) != -1) {
            strResult += new String(buffer,0,length,"utf-8");

        }
        System.out.println("strResult:="+strResult);
        //传递参数
        System.out.println("reponse:="+conn.getResponseMessage());
        System.out.println("reponcode:="+conn.getResponseCode());
        return  conn.getResponseCode()+"";

    }

    //digest 摘要认证
//    WWW-Authentication：用来定义使用何种方式（Basic、Digest、Bearer等）去进行认证以获取受保护的资源
//    realm：表示Web服务器中受保护文档的安全域（比如公司财务信息域和公司员工信息域），用来指示需要哪个域的用户名和密码
//    qop：保护质量，包含auth（默认的）和auth-int（增加了报文完整性检测）两种策略，（可以为空，但是）不推荐为空值
//    nonce：服务端向客户端发送质询时附带的一个随机数，这个数会经常发生变化。客户端计算密码摘要时将其附加上去，使得多次生成同一用户的密码摘要各不相同，用来防止重放攻击
//    nc：nonce计数器，是一个16进制的数值，表示同一nonce下客户端发送出请求的数量。例如，在响应的第一个请求中，客户端将发送“nc=00000001”。这个指示值的目的是让服务器保持这个计数器的一个副本，以便检测重复的请求
//    cnonce：客户端随机数，这是一个不透明的字符串值，由客户端提供，并且客户端和服务器都会使用，以避免用明文文本。这使得双方都可以查验对方的身份，并对消息的完整性提供一些保护
//    response：这是由用户代理软件计算出的一个字符串，以证明用户知道口令
//    Authorization-Info：用于返回一些与授权会话相关的附加信息
//    nextnonce：下一个服务端随机数，使客户端可以预先发送正确的摘要
//    rspauth：响应摘要，用于客户端对服务端进行认证
//    stale：当密码摘要使用的随机数过期时，服务器可以返回一个附带有新随机数的401响应，并指定stale=true，表示服务器在告知客户端用新的随机数来重试，而不再要求用户重新输入用户名和密码了

    /*1.客户端发现是401响应，表示需要认证，需要将用户名和密码加上realm经过md5加密生成的response放到Authorization的请求头中发送给服务器
      如果 algorithm 的值为MD5或者未指定
      HA1 = MD5(username:realm:password)
      如果qop的值为auth或者未指定
      HA2 = MD5(method:digestURL)
      则response的值为 MD5(HA1:nonce:nonceCount:cnonce:qop:HA2)
    */

    private static String getResponseCkInfo(Map<String, String> map_FirstReturn, List<String> countList) {
        //HA1:HD:HA2
        String username =  "admin";
        String pwd = "huawei@123";
        String realm = map_FirstReturn.get("realm");
        String nonce = map_FirstReturn.get("nonce");
        String qop = map_FirstReturn.get("qop");
        String noncecount = getHex(countList.size());
        String cnonce= "248a286a6dda379e";
        String method = "POST";
        String uri = "/VIID/System/UnRegister";

        //		String HA1 = MD5.baseMd5(username+":"+realm+":"+pwd);
        //		String HD = nonce+":::"+qop;
        //		String HA2= MD5.baseMd5(method+":"+uri);

        String HA1 = MD5.baseMd5(username+":"+realm+":"+pwd);
        String HD = nonce+":"+noncecount+":"+cnonce+":"+qop;
        String HA2= MD5.baseMd5(method+":"+uri);
        //		String response =  MD5.baseMd5(HA1+":"+HD+":"+HA2);
        //		MD5(MD5(A1):<nonce>:<nc>:<cnonce>:<qop>:MD5(A2))
        String response = MD5.baseMd5(HA1+":"+nonce+":"+noncecount+":"+cnonce+":"+qop+":"+HA2);
        String Authorization = "Digest ";
        Authorization+="username=\""+username+"\", ";
        Authorization+="realm=\""+realm+"\", ";
        Authorization+="qop=\""+qop+"\", ";
        Authorization+="nonce=\""+nonce+"\", ";
        Authorization+="uri=\""+uri+"\", ";
        Authorization+="cnonce=\""+cnonce+"\", ";
        //		Authorization+="cnonce=\"\", ";
        Authorization+="nc=\""+noncecount+"\", ";
        //		Authorization+="nc=, ";
        Authorization+="response=\""+response+"\"";

        //		Authorization: Digest username="xx",realm="xx",qop="auth",nonce="xx",uri="path",cnonce="xx",nc=00000001,response="xx",opaque="xx"
        //		String Authorization = "{\"username\":\""+username+"\",\"realm\":\""+realm+"\",\"qop\":\""+qop+"\""
        //				+ ",\"uri\":\""+uri+"\",\"cnonce\":\""+cnonce+"\",\"nc\":"+noncecount+",\"response\":\""+response+"\"}";;
        //        Authorization = "Digest username=\"admin\", realm=\"com.stevex.demo\", nonce=\"MTUzMDI0NTMzNTA1NDplOTNjYmMyNzRhNzU1MzNlODFlMWRjZWZmYjEwN2MwNg==\", uri=\"/demo/list\", qop=auth, nc=, cnonce=\"\", response=\"c4d517a96b923ba6b134caaf11c305cb\", opaque=\"\"";
        return Authorization;
    }

    /*
     * 将请求次数转为八位16进制
     */
    private static String getHex(int size) {
        String hex = Integer.toHexString(size);
        if(hex.length()<8){
            int l = 8-hex.length();
            String zero = "";
            for (int i = 0; i < l; i++) {
                zero+="0";
            }
            hex = zero+hex;
        }
        return hex;
    }




/*
Accept: application/json,application/*+json

Content-Type: application/VIID+JSON;charset=UTF-8

Connection: keepalive

User-Identify:34020000001110000001

User-Agent: libghttp/1.0

Content-Length: 65
 */


    public static String restConnect(String url,String method,String param,String authentication) {
        String strResult="";
        try {
            URL restUrl=new URL(url);
            HttpURLConnection conn = (HttpURLConnection) restUrl.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod(method);
            conn.setUseCaches(false);
            //			conn.setRequestProperty("Accept-Charset", "UTF-8");
            //			conn.setRequestProperty("contentType", "UTF-8");
            //设置访问提交模式，表单提交
            conn.setRequestProperty("Content-Type","application/viid+json");
            conn.setRequestProperty("User-Identify",authentication);
            conn.setRequestProperty("Connection","keepalive");
            conn.setConnectTimeout(10000);//连接超时 单位毫秒
            conn.setReadTimeout(5000);//读取超时 单位毫秒
            //传递参数
            if (param != null && !"".equals(param)) {
                byte[] bypes = param.toString().getBytes("utf-8");
                conn.getOutputStream().write(bypes);
            }
            conn.connect();
            InputStream inStream=conn.getInputStream();
            byte[] buffer = new byte[10240];
            int length = 0;
            while ((length = inStream.read(buffer)) != -1) {
                strResult += new String(buffer,0,length,"utf-8");

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return strResult;
    }

}
